package com.ajmd.onlineexam.service;

import com.ajmd.onlineexam.config.MultiRequestBody;
import com.ajmd.onlineexam.entity.*;
import com.ajmd.onlineexam.enumeration.StaticFinalValue;
import com.ajmd.onlineexam.mapper.ExamMapper;
import com.ajmd.onlineexam.mapper.PersonExamMapper;
import com.ajmd.onlineexam.mapper.StudentMapper;
import com.ajmd.onlineexam.mapper.TestPaperMapper;
import com.ajmd.onlineexam.vo.ExamVO;
import com.ajmd.onlineexam.vo.TeamVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ajmd
 * @since 2023/5/3 16:13
 */
@Service
public class ExamService {
    @Resource
    private ExamMapper examMapper;
    @Resource
    private StudentMapper studentMapper;
    @Resource
    private MessageService messageService;
    @Resource
    private PersonExamService personExamService;
    @Resource
    private PersonExamMapper personExamMapper;
    @Resource
    private TestPaperMapper testPaperMapper;
    @Resource
    private TeamService teamService;
    @Resource
    private ExamQuestionService examQuestionService;

    public ExamPO getOne(String examId){
        return examMapper.selectById(examId);
    }

    public ExamVO getOneVO(String examId){
        ExamVO examVO = new ExamVO();
        ExamPO examPO = examMapper.selectById(examId);
        if(ObjectUtils.isEmpty(examPO)){
            return examVO;
        }
        BeanUtils.copyProperties(examPO,examVO);
        TestPaperPO testPaperPO = testPaperMapper.selectById(examPO.getTestPaperId());
        if(ObjectUtils.isNotEmpty(testPaperPO)){
            examVO.setTotalCount(testPaperPO.getTotalCount());
            examVO.setMaxScore(testPaperPO.getMaxScore());
        }

        String examinees = examPO.getExaminees();
        String[] teamIds = examinees.split("\\|\\|\\|"); // 使用双反斜杠对竖线进行转义
        List<String> teamIdList = Arrays.asList(teamIds); // 将数组转换为 List
        List<TeamPO> teamPOList = teamService.getList(teamIdList);
        List<TeamVO> teamVOS = new ArrayList<>();
        if(ObjectUtils.isEmpty(teamPOList)){
            examVO.setTeamVOList(teamVOS);
            return examVO;
        }
        for(TeamPO teamPO:teamPOList){
            TeamVO teamVO = new TeamVO();
            teamVO.setId(teamPO.getId());
            teamVO.setTeamName(teamPO.getTeamName());
            teamVOS.add(teamVO);
        }
        examVO.setTeamVOList(teamVOS);
        return examVO;
    }

    @Transactional
    public int addOrUpdateExam(ExamPO examPO,Boolean publishReminder){
        if(ObjectUtils.isEmpty(examPO.getStartTime())){
            //没有设置开考时间 则默认当前时间，且考试状态为进行中
            examPO.setStatus(StaticFinalValue.IN_PROGRESS);
            examPO.setStartTime(new Timestamp(System.currentTimeMillis()));
        }
        Boolean isEdit = ObjectUtils.isNotEmpty(examPO.getId());
        int num=0;
        if(isEdit){
            num = examMapper.updateById(examPO);
            //删除原来生成的考生考试记录
            personExamService.batchDelete(examPO.getId());
            //删除原来实例化的考试试题、选项、图片
            examQuestionService.deleteExamQuestions(examPO.getId());
        }else{
            examPO.setId(UUID.randomUUID().toString());
            num = examMapper.insert(examPO);
        }
        if(num==0){
            return num;
        }
        //处理考试对象
        Set<String> studentIds = getStudentIds(examPO.getExaminees());
        //生成考生考试表
        personExamService.batchAdd(studentIds,examPO.getId());
        //生成考试试题表(实例化试题
        examQuestionService.copyTestPaper(examPO.getId(),examPO.getTestPaperId());
        //发布考试时是否通知
        if(publishReminder){
            sendMsg(examPO, studentIds);
        }
        return num;
    }

    private Set<String> getStudentIds(String examinees) {
        //处理考试对象
        List<String> teamIds = Arrays.asList(examinees.split("\\|\\|\\|"));
        LambdaQueryWrapper<StudentPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(StudentPO::getTeamId,teamIds);
        List<StudentPO> studentPOS = studentMapper.selectList(lambdaQueryWrapper);
        return studentPOS.stream().map(StudentPO::getAccount).collect(Collectors.toSet());
    }

    private int sendMsg(ExamPO examPO, Set<String> studentIds) {
        String msg="考试通知！您有一场考试《"+ examPO.getExamName()+"》，考试时间"+ examPO.getStartTime();
        //往消息表中增加记录
        Map<String, Object> value = new HashMap<>();
        value.put("msg",msg);
        value.put("sendAccount", examPO.getCreatePerson());
        value.put("studentIds", studentIds);
        value.put("sendType", examPO.getCreatorType());
        Map<String, Map<String, Object>> stringMapMap = new HashMap<>();
        stringMapMap.put(examPO.getId(),value);
        return messageService.batchInsert(stringMapMap);
//            messageService.batchInsertByStudentIds(studentIds,examPO.getCreatePerson(),msg);
        //todo 发送邮件
    }

    public int sendMsg(ExamPO examPO){
        Set<String> studentIds = getStudentIds(examPO.getExaminees());
        return sendMsg(examPO,studentIds);
    }


    /**
     * 分页查询考试
     * @param currentPage
     * @param pageSize
     * @param searchParam
     * @return
     */
    public Page<ExamPO> getExamPage(Integer currentPage,Integer pageSize,SearchParam searchParam){
        LambdaQueryWrapper<ExamPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if(ObjectUtils.isNotEmpty(searchParam.getSearchValue())){
            lambdaQueryWrapper.like(ExamPO::getExamName,searchParam.getSearchValue());
        }
        //时间过滤
        if(ObjectUtils.isNotEmpty(searchParam.getDuring()) && !StaticFinalValue.ALL_EXAM.equals(searchParam.getDuring())){
            long current = System.currentTimeMillis();
            Timestamp startTime = new Timestamp(current - searchParam.getDuring()*24*60*60*1000);
            Timestamp endTime = new Timestamp(current + searchParam.getDuring()*24*60*60*1000);
            lambdaQueryWrapper.between(ExamPO::getStartTime,startTime,endTime);
        }
        Page<ExamPO> page = new Page<>(currentPage,pageSize);
        return examMapper.selectPage(page,lambdaQueryWrapper);
    }

    /**
     * 删除单个考试，不允许批量删除
     * @param examId
     * @return
     */
    public int examDelete(String examId){
        //查询是否有考生开考记录
        boolean hasPersonExamRecord = personExamService.hasPersonExamRecord(examId);
        if(!hasPersonExamRecord){
            //没有考生开考记录
            //删除考试-试题信息（发布时已将试卷-试题实例化到考试-试题表
            examQuestionService.deleteExamQuestions(examId);
            //删除考生-考试信息（发布考试时已为每一个考生初始化考试
            personExamService.batchDelete(examId);
        }
        // 考生-答案信息 无需删除
        //删除考试
        return examMapper.deleteById(examId);
    }

    /**
     * 关闭考试
     * @param examId
     * @return
     */
    public int closeExam(String examId){
        LambdaUpdateWrapper<ExamPO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(ExamPO::getStatus,StaticFinalValue.CLOSED)
                .eq(ExamPO::getId,examId);
        return examMapper.update(null,updateWrapper);
    }


    /**
     * 考生分页查询本人考试
     * @param account
     * @param currentPage
     * @param pageSize
     * @param searchParam
     */
    public IPage<ExamVO> studentGetPage(String account, Integer currentPage, Integer pageSize, SearchParam searchParam){

        //查询考生考试表，
//        LambdaQueryWrapper<PersonExamPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//        lambdaQueryWrapper.
//
//        StudentPO studentPO = studentMapper.selectById(account);
//
//
//
//        LambdaQueryWrapper<ExamPO> queryWrapper = new LambdaQueryWrapper<>();
//        if(ObjectUtils.isNotEmpty(searchParam.getSearchValue())){
//            queryWrapper.eq(ExamPO::getExamName,searchParam.getSearchValue());
//        }
//        queryWrapper.ne(ExamPO::getStatus,StaticFinalValue.CLOSED)
//                .like(ExamPO::getExaminees,studentPO.getTeamId())
//                .orderByDesc(ExamPO::getCreateTime);
//        Page<ExamPO> page = new Page<>(currentPage, pageSize);
//        return examMapper.selectPage(page,queryWrapper);
        Page<ExamVO> page = new Page<>(currentPage, pageSize);
        return  examMapper.studentSelectExams(page,account,searchParam.getSearchValue());
    }

    /**
     * 考生获取考试记录
     * @param account
     * @param examId
     * @param currentPage
     * @param pageSize
     * @return
     */
    public Page<PersonExamPO> getExamRecords(String account,String examId,
                                             Integer currentPage, Integer pageSize){

        Page<PersonExamPO> page = new Page<>(currentPage, pageSize);
        LambdaQueryWrapper<PersonExamPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PersonExamPO::getStudentId,account)
                .eq(PersonExamPO::getExamId,examId)
                .gt(PersonExamPO::getStatus,StaticFinalValue.EXAMINED)
                .orderByDesc(PersonExamPO::getScore)
                .orderByDesc(PersonExamPO::getEnterTime);
        return personExamMapper.selectPage(page, queryWrapper);
    }
}
